import Zombies
import Plantes
import pygame as pg
import pymunk as pm
import threading
import time
import copy
import queue
import random
import sys,os
import yaml
from typing import Dict,Any


def resource_path(relative_path):
    if getattr(sys, 'frozen', False):
        base_path = sys._MEIPASS
    else:
        base_path = os.path.abspath(".")
        # base_path = os.path.dirname(os.path.abspath(__file__))
    return os.path.join(base_path, relative_path)

def load_config(yaml_path) -> Dict[str, Any]:
    """
    读取指定目录的yaml文件

    :param yaml_path: 相对当前的yaml文件绝对路径
    :return:
    """
    # 加上 ,encoding='utf-8'，处理配置文件中含中文出现乱码的情况。
    with open(yaml_path, "r", encoding="utf-8") as f:
        return yaml.safe_load(f)


config = load_config('config.yaml')
startTime=int(time.time())
pg.init()
clock = pg.time.Clock()
screen = pg.display.set_mode((800,600))
pg.display.set_caption("植物大战僵尸")
icon = pg.image.load(resource_path("images/screenshot1.jpg"))
pg.display.set_icon(icon)
backgroung_img = pg.image.load(resource_path("images/background1.jpg"))
SeedBank_img = pg.image.load(resource_path("images/SeedBank.png"))
SeedPacket_Larger_img = pg.image.load(resource_path("images/SeedPacket_Larger.png"))
try:
    pg.mixer.music.load(resource_path('audio/BGMusic.mp3'))
    pg.mixer.music.play(loops=-1)
except:
    pass


class SoundEffect:
    def __init__(self):
        self.launch=pg.mixer.Sound(resource_path("audio/launch.mp3"))
try:
    soundEffect=SoundEffect()
except:
    pass
score = 0
sun = 0

player_1 = Plantes.PeaShooter()
if config['twoPlayer']:
    player_2 = Plantes.PeaShooter()
Pea = []
Zombie = []

isWin=None

# def distance(bx,by,ex,ey):
#     a = bx - ex
#     b = by - ey
#     return math.sqrt(a*a+b*b)

def draw_SeedBank():
    screen.blit(SeedBank_img,(0,0))

def draw_img():
    screen.blit(backgroung_img,(-220,0))
    screen.blit(player_1.img,(player_1.x,player_1.y))
    if config['twoPlayer']:
        screen.blit(player_2.img,(player_2.x,player_2.y))

def draw_Peas(): 
    for b in Pea:
        screen.blit(b.img,(b.x,b.y))

def draw_Zombie():
    for e in Zombie:
        pg.draw.rect(screen,(255,255,255),(e.x,e.y-40,40,10),2)
        pg.draw.rect(screen, e.healthbarColor, [e.x+2,e.y-38,e.healthy/e.maxhealthy*36,6],0)
        screen.blit(e.img,(e.x,e.y-35))

font=pg.font.Font(resource_path("fonts/title.ttf"), 180)
countDownFont=pg.font.Font(resource_path("fonts/countDown.ttf"), 64)
sunFont=pg.font.Font(resource_path("fonts/countDown.ttf"), 24)

def draw_sun():
    try:
        sun_render = sunFont.render(f"{sun}",True,(0,0,0))
    except:
        os._exit(0)
    screen.blit(sun_render,(15,60))

def drawContDown():
    countDown=countDownFont.render(str(150+startTime-int(time.time())),1,(255,0,0))
    screen.blit(countDown,(700,10))

def draw():
    global isWin
    try:
        while True:
            clock.tick(60)
            if isWin!=None:
                break
            draw_img()
            draw_SeedBank()
            draw_sun()
            draw_Peas()
            draw_Zombie()
            drawContDown()
            pg.display.update()
        if isWin:
            while True:
                clock.tick(60)
                screen.fill((215,119,6))
                winTips=font.render("胜利",1,(255,255,255))
                screen.blit(winTips,(200,200))
                pg.display.update()
        else:
            while True:
                clock.tick(60)
                screen.fill((104,33,122))
                lossTips=font.render("失败",1,(255,255,255))
                screen.blit(lossTips,(200,200))
                pg.display.update()
    except:
        os._exit(1)

def doKeyEvent(key):
    if key == pg.K_RIGHT and player_1.x < (8 * 80) + 25:
        player_1.x += 80
    elif key == pg.K_LEFT and player_1.x > (1 * 80) + 25:
        player_1.x += -80
    elif key == pg.K_UP and player_1.y > (1 * 80) + 25:
        player_1.y += -100
    elif key == pg.K_DOWN and player_1.y < (5 * 80) + 25:
        player_1.y += 100
    elif key == pg.K_SPACE:
        Pea.append(player_1.bullet(player_1))
        try:
            soundEffect.launch.play()
        except:
            pass
    if config['twoPlayer']:
        if key == pg.K_d and player_2.x < (8 * 80) + 25:
            player_2.x += 80
        elif key == pg.K_a and player_2.x > (1 * 80) + 25:
            player_2.x += -80
        elif key == pg.K_w and player_2.y > (1 * 80) + 25:
            player_2.y += -100
        elif key == pg.K_s and player_2.y < (5 * 80) + 25:
            player_2.y += 100
        elif key == pg.K_q:
            Pea.append(player_2.bullet(player_2))
            try:
                soundEffect.launch.play()
            except:
                pass

def logic():
    global Pea,isWin
    i=0
    while True:
        clock.tick(150)
        if int(time.time())-startTime>150:
            isWin = True
        if isWin!=None:
            return
        i=(i+1)%15
        if not i:
            for key in copy.copy(keyList):
                if keyList.get(key) == None or float(time.time()) - keyList.get(key) < 0.3:
                    continue
                doKeyEvent(key)
        while not keyDownList.empty():
            doKeyEvent(keyDownList.get())
        for e in Zombie:
            e.x += e.speed
            try:
                for eff in e.statuses.values():
                    eff.effect()
            except RuntimeError:
                pass
            if e.x < 0:
                isWin=False
        Pea = list(filter(None, Pea))
        if len(Zombie)<=15 and random.randint(1,max(50,135-int(time.time())+startTime))==1:
            Zombie.append(Zombies.Zombie(parent=Zombie))
        for b in Pea:
            if b.hit(Zombies=Zombie,Peas=Pea):
                try:
                    Pea.remove(b)
                except:
                    pass
            b.move()
            if b.x > 800 or b.x < 0 or b.y < -50 or b.y > 650:
                try:
                    Pea.remove(b)
                except:
                    break
                break
        
keyList={}
keyDownList=queue.Queue()
渲染 = threading.Thread(target=draw,name= "渲染",daemon=True)
逻辑 = threading.Thread(target=logic,name= "逻辑",daemon=True)
渲染.start()
逻辑.start()
while True:
    for event in pg.event.get():
        if event.type == pg.QUIT:
            pg.quit()
            quit()
        if event.type == pg.KEYDOWN:
            keyList[event.key]=float(time.time())
            keyDownList.put(event.key)
            if event.key == pg.K_KP_1:
                player_1 = Plantes.PeaShooter(player_1.x,player_1.y)
            elif event.key == pg.K_KP_2:
                player_1 = Plantes.sinPeaShooter(player_1.x,player_1.y)
            elif event.key == pg.K_KP_3:
                player_1 = Plantes.bombPeaShooter(player_1.x,player_1.y)
            elif event.key == pg.K_KP_4:
                player_1 = Plantes.poisonousPeaShooter(player_1.x,player_1.y)
            if config['twoPlayer']:
                if event.key == pg.K_1:
                    player_2 = Plantes.PeaShooter(player_2.x,player_2.y)
                elif event.key == pg.K_2:
                    player_2 = Plantes.sinPeaShooter(player_2.x,player_2.y)
                elif event.key == pg.K_3:
                    player_2 = Plantes.bombPeaShooter(player_2.x,player_2.y)
                elif event.key == pg.K_4:
                    player_2 = Plantes.poisonousPeaShooter(player_2.x,player_2.y)
                
        if event.type == pg.KEYUP:
            del keyList[event.key]